﻿#region Header

/*
Remote views based on linq
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading;
using InterLinq.Expressions;
using Sebarf.Core.Interfaces;
using Sebarf.Diagnostics.Interfaces;
using Sebastof.Serialisation;
using Sebastof.Services.Interfaces;

#endregion

namespace InterLinq.Types {
	/// <summary>
	/// Transport multiple object that are not anonymous
	/// </summary>
	[Serializable]
	public class CollectionTransporter {
		#region Public Properties

		/// <summary>
		/// Gets the orginal values
		/// </summary>
		public IEnumerable Values { get; private set; }

		/// <summary>
		/// transfered metadata
		/// </summary>
		public IMetadataLocatorService TransferedMetadata { get; set; }

		public Dictionary<string, Dictionary<string, object>> TransferedData { get; set; }

		#endregion

		#region Public Methods

		/// <summary>
		/// Ctr
		/// </summary>
		/// <param name="values"></param>
		public CollectionTransporter(IServiceLocatorService ctx, IEnumerable values) {
			Values = values;
			TransferedMetadata = new MetadataLocatorRegisterService();
			TransferedData = new Dictionary<string, Dictionary<string, object>>();
			m_dataHandlingStrategyService = ctx.GetRegisteredService<ISerializationDataHandlingStrategyService>();
			m_objectTreeHelperService = ctx.GetRegisteredService<IObjectTreeFlattenerService>();

			if (values is string) {
				return;
			}
			try {
				var objectIdentifierLocatorService = ctx.GetRegisteredService<IObjectIdentifierLocatorService>();
				var omapperRegister = ctx.GetRegisteredService<IObjectMappingRegisterService>();
				Monitor.Enter(omapperRegister);
				foreach (object obj in values) {
					IList<IFlattenTreeObjectEntry> nestedobjs = m_objectTreeHelperService.GetFlattenTree(obj);
					foreach (IFlattenTreeObjectEntry entry in nestedobjs) {
						object nestedo = entry.ObjectTreeEntry;
						if (nestedo == null) {
							continue;
						}
						if (nestedo is Expression) {
							TransferedMetadata.Add(entry.ObjectTreeEntry, "Expressions", (nestedo as Expression).MakeSerializable());
							entry.ReplaceValueOnTreeBy(null);
						}

						TransferedMetadata.Add(nestedo, "UniqueIdentifier", objectIdentifierLocatorService.GetIdentityForObject(nestedo));

						omapperRegister.AddMapping(objectIdentifierLocatorService.GetIdentityForObject(nestedo), nestedo);

						if (nestedo is ISebastofApplicationObject) {
							var iObject = nestedo as ISebastofApplicationObject;
							if (!TransferedData.ContainsKey(iObject.Id)) {
								TransferedData.Add(iObject.Id, new Dictionary<string, object>());
							}
							foreach (var val in m_dataHandlingStrategyService.GetDataToTransferFromObject(nestedo)) {
								if (!TransferedData[iObject.Id].ContainsKey(val.Key)) {
									TransferedData[iObject.Id].Add(val.Key, val.Value);
								}
							}
							//IInterLinqApplicationObjectImpl iObject = nestedo as IInterLinqApplicationObjectImpl;
							//if (!TransferedData.ContainsKey(iObject.Id)) {
							//    TransferedData.Add(iObject.Id, new Dictionary<string, object>());
							//}
							//foreach (var val in iObject.GetValues()) {
							//    TransferedData[iObject.Id].Add(val.Key, val.Value);
							//}
						}
					}
				}
				Monitor.Exit(omapperRegister);
			}
			catch (Exception err) {
				Check.AssertException(false, err.Message + "\n" + err.StackTrace);
				throw;
			}
		}

		#endregion

		#region Private Fields

		[NonSerialized]
		private ISerializationDataHandlingStrategyService m_dataHandlingStrategyService;

		[NonSerialized]
		private IObjectTreeFlattenerService m_objectTreeHelperService;

		#endregion
	}
}